/**
 * CoffeeMilk (C) 2010 Amen Hamdan
 * 
 * See the NOTICE file distributed with this work for additional 
 * information regarding copyright ownership.  This file is licenses
 * to you under the Apache License, Version 2.0 (the "License"); you 
 * may not use this file except in compliance with the License.  You 
 * may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
 * implied. See the License for the specific language governing 
 * permissions and limitations under the License.    
 * 
 */
package ameen.rtm.coffeemilk.ui.util;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.SimpleDateFormat;

import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

import ameen.rtm.coffeemilk.RtmTaskListModel;
import ameen.rtm.lib.types.RtmList;
import ameen.rtm.lib.types.RtmTask;
import ameen.rtm.lib.types.TasksVector.SortOrder;

public class ToolbarFactory {
	private static final ImageIcon prio1Image = new ImageIcon(ToolbarFactory.class.getResource("/ameen/rtm/coffeemilk/ui/prio1_label.png"));;
	private static final ImageIcon prio2Image = new ImageIcon(ToolbarFactory.class.getResource("/ameen/rtm/coffeemilk/ui/prio2_label.png"));
	private static final ImageIcon prio3Image = new ImageIcon(ToolbarFactory.class.getResource("/ameen/rtm/coffeemilk/ui/prio3_label.png"));
	private static final SimpleDateFormat fDateFormatter = new SimpleDateFormat("d MMM yyyy");
	
	private static TaggedKeyAdapter nameKeyAdapter = null;
	private static TaggedKeyAdapter dueDateAdapter = null;
	private static TaggedKeyAdapter tagsKeyAdapter = null;
	
	public static final JPopupMenu createPrioritySelectionPopup(final RtmTaskListModel taskListModel, final RtmList currentEntry, final int row) {
		final JPopupMenu menu = new JPopupMenu(); 
		final JToolBar tbar = new JToolBar();
		tbar.setFloatable(false);
		
		JButton setPrio0Button = new JButton("unset prio");
		setPrio0Button.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				SwingUtilities.invokeLater(new Runnable() {
					
					@Override
					public void run() {
						menu.setVisible(false);
						RtmTask currentTask = taskListModel.getTasks(currentEntry).get(row);
						currentTask.setPriority("N");
					}
				});
			}
		});
		JButton setPrio1Button = new JButton("set to prio 1");
		setPrio1Button.setIcon(prio1Image);
		setPrio1Button.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				SwingUtilities.invokeLater(new Runnable() {
					@Override
					public void run() {
						menu.setVisible(false);
						RtmTask currentTask = taskListModel.getTasks(currentEntry).get(row);
						currentTask.setPriority("1");
					}
				});
			}
		});
		JButton setPrio2Button = new JButton("set to prio 2");
		setPrio2Button.setIcon(prio2Image);
		setPrio2Button.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				
				SwingUtilities.invokeLater(new Runnable() {
					@Override
					public void run() {
						menu.setVisible(false);
						RtmTask currentTask = taskListModel.getTasks(currentEntry).get(row);
						currentTask.setPriority("2");
					}
				});
			}
		});
		JButton setPrio3Button = new JButton("set to prio 3");
		setPrio3Button.setIcon(prio3Image);
		setPrio3Button.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				SwingUtilities.invokeLater(new Runnable() {
					
					@Override
					public void run() {
						menu.setVisible(false);
						RtmTask currentTask = taskListModel.getTasks(currentEntry).get(row);
						currentTask.setPriority("3");
					}
				});
				
			}
		});
		tbar.add(setPrio0Button);
		tbar.add(new JSeparator(SwingConstants.VERTICAL));
		tbar.add(setPrio1Button);
		tbar.add(new JSeparator(SwingConstants.VERTICAL));
		tbar.add(setPrio2Button);
		tbar.add(new JSeparator(SwingConstants.VERTICAL));
		tbar.add(setPrio3Button);
		menu.add(tbar);
		return menu;
	}

	public static JPopupMenu createEditTaskPopup(final RtmTaskListModel taskListModel, final RtmList currentEntry, final int row) {
		final JPopupMenu menu = new JPopupMenu(); 
		final RtmTask currentTask = taskListModel.getTasks(currentEntry).get(row);
		
		// prepare the toolbars
		JToolBar nameEditToolbar = new JToolBar();
		JToolBar notesEditToolbar = new JToolBar();
		JToolBar tagsDueDateToolbar = new JToolBar();
		JToolBar updateButtonToolbar = new JToolBar();
		
		nameEditToolbar.setFloatable(false);
		notesEditToolbar.setFloatable(false);
		tagsDueDateToolbar.setFloatable(false);
		updateButtonToolbar.setFloatable(false);
	
		// prepare the text fields
		final JTextField nameTextField = new JTextField(currentTask.getName());
		final JTextField dueDateTextField;
		if(currentTask.getDueDate() != null) {
			dueDateTextField = new JTextField(fDateFormatter.format(currentTask.getDueDate()));
		} else {
			dueDateTextField = new JTextField();
		}
		JTextField notesTextField = new JTextField();
		final JTextField tagsTextField = new JTextField(currentTask.getTagsString());
		
		dueDateTextField.setPreferredSize(new Dimension(80, 20));
		nameTextField.setPreferredSize(new Dimension(250, 20));
		notesTextField.setPreferredSize(new Dimension(100, 20));
		tagsTextField.setPreferredSize(new Dimension(100, 20));
		
		// TODO: removed the duplicate Tagged Key Adapter use
		nameKeyAdapter = new TaggedKeyAdapter() {
			@Override
			public void keyTyped(KeyEvent e) {
				if(e.getKeyChar() == KeyEvent.VK_ENTER) {
					tag();
					
					SwingUtilities.invokeLater(new Runnable() {
						
						@Override
						public void run() {
							if(nameKeyAdapter.isTagged()) currentTask.setName(nameTextField.getText());
							if(dueDateAdapter.isTagged()) currentTask.updateDueDate(dueDateTextField.getText());
							if(tagsKeyAdapter.isTagged()) currentTask.updateTags(tagsTextField.getText());
							menu.setVisible(false);
						}
					});
				}
			}
		};
		dueDateAdapter = new TaggedKeyAdapter() {
			@Override
			public void keyTyped(KeyEvent e) {
				tag();
				if(e.getKeyChar() == KeyEvent.VK_ENTER) {
					SwingUtilities.invokeLater(new Runnable() {
						
						@Override
						public void run() {
							if(nameKeyAdapter.isTagged()) currentTask.setName(nameTextField.getText());
							if(dueDateAdapter.isTagged()) currentTask.updateDueDate(dueDateTextField.getText());
							if(tagsKeyAdapter.isTagged()) currentTask.updateTags(tagsTextField.getText());
						}
					});
					menu.setVisible(false);
				}
			}
		};
		
		tagsKeyAdapter = new TaggedKeyAdapter() {
			@Override
			public void keyTyped(KeyEvent e) {
				tag();
				if(e.getKeyChar() == KeyEvent.VK_ENTER) {
					SwingUtilities.invokeLater(new Runnable() {
						
						@Override
						public void run() {
							if(nameKeyAdapter.isTagged()) currentTask.setName(nameTextField.getText());
							if(dueDateAdapter.isTagged()) currentTask.updateDueDate(dueDateTextField.getText());
							if(tagsKeyAdapter.isTagged()) currentTask.updateTags(tagsTextField.getText());
					}
					});
					menu.setVisible(false);
				}
			}
		};
		nameTextField.addKeyListener(nameKeyAdapter);
		dueDateTextField.addKeyListener(dueDateAdapter);
		tagsTextField.addKeyListener(tagsKeyAdapter);
	
		// construct the pop up
		
		// #1 the task name toolbar
		JLabel jLabel = new JLabel("Task: ");
		jLabel.setPreferredSize(new Dimension(60,20));
		nameEditToolbar.add(jLabel);
		nameEditToolbar.add(nameTextField);
		menu.add(nameEditToolbar);
		
		// #2 due date & tags toolbar
		jLabel = new JLabel("Due Date: ");
		jLabel.setPreferredSize(new Dimension(60,20));
		tagsDueDateToolbar.add(jLabel);
		tagsDueDateToolbar.add(dueDateTextField);
		jLabel = new JLabel(" - Tags: ");
		tagsDueDateToolbar.add(jLabel);
		tagsDueDateToolbar.add(tagsTextField);
		menu.add(nameEditToolbar);
		menu.add(tagsDueDateToolbar);

		// #3 the notes toolbar 
		jLabel = new JLabel("Notes: ");
		jLabel.setPreferredSize(new Dimension(60,20));
		notesEditToolbar.add(jLabel);
		notesEditToolbar.add(notesTextField);
//		menu.add(notesEditToolbar);
	
	
		// #4 add the commit button
		menu.add(new JSeparator(SwingConstants.HORIZONTAL));
		JButton commitButton = new JButton(" update ");
		commitButton.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				SwingUtilities.invokeLater(new Runnable() {
					
					@Override
					public void run() {
						currentTask.setName(nameTextField.getText());
						currentTask.updateDueDate(dueDateTextField.getText());
					}
				});
				menu.setVisible(false);
			}
		});

		updateButtonToolbar.add(commitButton);
		menu.add(updateButtonToolbar);
		
		return menu;
	}

	public static JPopupMenu createSortCriteriaPopup(TaskSortHandler sorter) {
		JPopupMenu menu = new JPopupMenu();

		JMenuItem headerItem = new JMenuItem("sort ascending");
		menu.add(headerItem);
		headerItem.setEnabled(false);
		menu.add(new SorterAction("by name", sorter, SortOrder.NAME_ASCENDING));
		menu.add(new SorterAction("by priority", sorter, SortOrder.PRIORITY_ASCENDING));
		menu.add(new SorterAction("by due date", sorter, SortOrder.DUEDATE_ASCENDING));
		
		menu.add(new JSeparator(SwingConstants.HORIZONTAL));
		headerItem = new JMenuItem("sort descending");
		headerItem.setEnabled(false);
		menu.add(headerItem);
		menu.add(new SorterAction("by name", sorter, SortOrder.NAME_DESCENDING));
		menu.add(new SorterAction("by priority", sorter, SortOrder.PRIORITY_DESCENDING));
		menu.add(new SorterAction("by due date", sorter, SortOrder.DUEDATE_DESCENDING));
	
		return menu;
	}
	
}

@SuppressWarnings("serial")
class SorterAction extends AbstractAction {
	private TaskSortHandler fSorter;
	private SortOrder fSortOrder;
		
	public SorterAction(String name, TaskSortHandler sorter, SortOrder sortOrder) {
		super(name);
		fSorter = sorter;
		fSortOrder = sortOrder;
	}
		
	@Override
	public void actionPerformed(ActionEvent e) {
		fSorter.updateSortOrder(fSortOrder);
	}

}

